using System;
using System.Configuration;
using System.Data;
using T.FAS.Runtime.Metadata.Entity.DataModel;
using T.FAS.Runtime.Base.Entity;
using T.FAS.Runtime.DataAccess.SPI;
using System.Linq;
using Newtonsoft.Json;
using System.Collections.Generic;
using T.ServiceComponent.Log.SPI;

namespace T.FAS.Runtime.DataAccess.Common
{
    public abstract class LogBase : IDACLogService
    {
        protected JsonSerializerSettings Setting = new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore };

        public ExecuteLogSetting ExecuteLogSetting { get; set; }

        public LogBase()
        {
            var s_logInfoStr = ConfigurationManager.AppSettings["ExecuteLogInfo"];
            if (!string.IsNullOrEmpty(s_logInfoStr))
            {
                try
                {
                    ExecuteLogSetting = JsonConvert.DeserializeObject<ExecuteLogSetting>(s_logInfoStr);
                }
                catch
                {
                    ExecuteLogSetting = GetDefaultLogSetting();
                }
            }
            else
            {
                ExecuteLogSetting = GetDefaultLogSetting();
            }
        }

        public abstract void Write(object obj, ExtLogInfo extLogInfo = null);
        public abstract void WriteChangeLog(List<DataChangeLog> changeLogs, ExtLogInfo extLogInfo = null);
        public abstract void WriteError(Exception er, string Msg = null, ExtLogInfo extLogInfo = null);
        public abstract void WriteSQL(string SQL, IDbDataParameter[] paras = null, SQLLogType type = SQLLogType.DQL, ExtLogInfo extLogInfo = null);
        public abstract void WriteStateChangeLog(List<StateMachineChangedMsg> msgs, ExtLogInfo extLogInfo = null);
        public abstract void CDOTraceLog(CompositeDataObject cdo, TRecord record, InjectionMethodType opType, string msg = null, object extObj = null);

        protected object GetCDOPkValue(CompositeDataObject cdo, TRecord record)
        {
            try
            {
                var cno = cdo.RootCompositeNodeObject;
                var pkCol = cno.DataObject.Columns.FirstOrDefault(c => c.IsPkColumn);
                if (pkCol == null)
                    throw new FasException(DataAccessErrorCode.CompositeDataObject.Error, string.Format(CommonStringClassCommon.TRecordCommonExtension_CNOGetPKValueFail,cno.CompositeDataObject?.Code,cno.DataObjectTableAlias));
                var pkVal = record.GetValue(pkCol.ColumnName);
                if (pkVal == null)
                    throw new FasException(DataAccessErrorCode.CompositeDataObject.Error, string.Format(CommonStringClassCommon.TRecordCommonExtension_TRecordGetPkColumnFail, cno.CompositeDataObject?.Code,cno.DataObjectTableAlias));
                return pkVal.ToString();
            }
            catch (Exception e)
            {
                throw new Exception(CommonStringClassCommon.TRecordCommonExtension_TRecordGetPKValueFail, e);
            }
        }

        public static ExecuteLogSetting GetDefaultLogSetting()
        {
            return new ExecuteLogSetting
            {
                IsLog = true,
                LogType = DacLogType.LogService,
                IsLogError = true,
                IsLogSQL = true,
            };
        }
    }
}